// Magic Software, Inc.
// http://www.magic-software.com
// Copyright (c) 2000, All Rights Reserved
//
// Source code from Magic Software is supplied under the terms of a license
// agreement and may not be copied or disclosed except in accordance with the
// terms of that agreement.  The various license agreements may be found at
// the Magic Software web site.  This file is subject to the license
//
// FREE SOURCE CODE
// http://www.magic-software.com/License/free.pdf

#include "MgcColor.h"
#include "MgcRTLib.h"

const MgcColor MgcColor::BLACK(0.0,0.0,0.0);
const MgcColor MgcColor::WHITE(1.0,1.0,1.0);

//----------------------------------------------------------------------------
MgcColor::MgcColor ()
{
    // For efficiency in construction of large arrays of colors,
    // the default constructor does not initialize a color.
}
//----------------------------------------------------------------------------
MgcColor::MgcColor (MgcReal fR, MgcReal fG, MgcReal fB)
{
    r = fR;
    g = fG;
    b = fB;
}
//----------------------------------------------------------------------------
MgcColor::MgcColor (const MgcColor& rkColor)
{
    r = rkColor.r;
    g = rkColor.g;
    b = rkColor.b;
}
//----------------------------------------------------------------------------
MgcReal& MgcColor::operator[] (int i) const
{
    // assert:  0 <= i < 3; r, g, b packed into 3*sizeof(MgcReal) bytes
    return (MgcReal&) *(&r + i);
}
//----------------------------------------------------------------------------
MgcColor::operator MgcReal* ()
{
    // assert:  r, g, b packed into 3*sizeof(MgcReal) bytes
    return &r;
}
//----------------------------------------------------------------------------
void MgcColor::Clamp ()
{
    if ( r < 0.0 )
        r = 0.0;
    else if ( r > 1.0 )
        r = 1.0;

    if ( g < 0.0 )
        g = 0.0;
    else if ( g > 1.0 )
        g = 1.0;

    if ( b < 0.0 )
        b = 0.0;
    else if ( b > 1.0 )
        b = 1.0;
}
//----------------------------------------------------------------------------
void MgcColor::ScaleByMax ()
{
    MgcReal fMax = r;
    if ( g > fMax )
        fMax = g;
    if ( b > fMax )
        fMax = b;

    if ( fMax > 1.0 )
    {
        MgcReal fInvMax = 1.0/fMax;
        r *= fInvMax;
        g *= fInvMax;
        b *= fInvMax;
    }
}
//----------------------------------------------------------------------------
MgcColor& MgcColor::operator= (const MgcColor& rkColor)
{
    r = rkColor.r;
    g = rkColor.g;
    b = rkColor.b;
    return *this;
}
//----------------------------------------------------------------------------
bool MgcColor::operator== (const MgcColor& rkColor) const
{
    return r == rkColor.r
        && g == rkColor.g
        && b == rkColor.b;
}
//----------------------------------------------------------------------------
bool MgcColor::operator!= (const MgcColor& rkColor) const
{
    return r != rkColor.r
        || g != rkColor.g
        || b != rkColor.b;
}
//----------------------------------------------------------------------------
MgcColor MgcColor::operator+ (const MgcColor& rkColor) const
{
    return MgcColor(r+rkColor.r,g+rkColor.g,b+rkColor.b);
}
//----------------------------------------------------------------------------
MgcColor MgcColor::operator- (const MgcColor& rkColor) const
{
    return MgcColor(r-rkColor.r,g-rkColor.g,b-rkColor.b);
}
//----------------------------------------------------------------------------
MgcColor MgcColor::operator* (const MgcColor& rkColor) const
{
    return MgcColor(r*rkColor.r,g*rkColor.g,b*rkColor.b);
}
//----------------------------------------------------------------------------
MgcColor MgcColor::operator/ (const MgcColor& rkColor) const
{
    assert( rkColor.r > 0.0
        &&  rkColor.g > 0.0
        &&  rkColor.b > 0.0 );

    return MgcColor(r/rkColor.r,g/rkColor.g,b/rkColor.b);
}
//----------------------------------------------------------------------------
MgcColor MgcColor::operator- () const
{
    return MgcColor(-r,-g,-b);
}
//----------------------------------------------------------------------------
MgcColor operator* (MgcReal fScalar, const MgcColor& rkColor)
{
    return MgcColor(fScalar*rkColor.r,fScalar*rkColor.g,fScalar*rkColor.b);
}
//----------------------------------------------------------------------------
MgcColor& MgcColor::operator+= (const MgcColor& rkColor)
{
    r += rkColor.r;
    g += rkColor.g;
    b += rkColor.b;
    return *this;
}
//----------------------------------------------------------------------------
MgcColor& MgcColor::operator-= (const MgcColor& rkColor)
{
    r -= rkColor.r;
    g -= rkColor.g;
    b -= rkColor.b;
    return *this;
}
//----------------------------------------------------------------------------
MgcColor& MgcColor::operator*= (const MgcColor& rkColor)
{
    r *= rkColor.r;
    g *= rkColor.g;
    b *= rkColor.b;
    return *this;
}
//----------------------------------------------------------------------------
MgcColor& MgcColor::operator/= (const MgcColor& rkColor)
{
    assert( rkColor.r > 0.0
        &&  rkColor.g > 0.0
        &&  rkColor.b > 0.0 );

    r /= rkColor.r;
    g /= rkColor.g;
    b /= rkColor.b;
    return *this;
}
//----------------------------------------------------------------------------
